package pojo;

import dao.QiziDao;
import service.GameService;

import java.util.LinkedHashMap;
import java.util.Map;

public class AI2 extends AI {
    private int depth;//dfs深度,也就是ai难度,建议使用2层及以下,2层以上下棋速度太慢
    public AI2(int N, int color,int chess, int depth) {//初始化
        super.N=N;
        super.color = color;
        super.chess=chess;
        this.depth=depth;
        buildNext();
    }
    public int run(int[][] map) {//计算下次下的坐标x,y,返回值为当前得分
        this.map=map;
        int score=changeMap()?AlphaBeta(depth,Integer.MIN_VALUE,Integer.MAX_VALUE,true):0;
        if(super.sum==1){//后手下法
            for(int i=-1;i<=1;i++){
                for(int j=-1;j<=1;j++){
                    if(startX-i>=0&&startX-i<15&&startY-j>=0&&startY-j<15&&map[startX-i][startY-j]==0){
                        x=startX-i;
                        y=startY-j;
                    }
                }
            }
        }
        recoverMap();
        return score;
    }
    private int AlphaBeta(int depth,int alpha,int beta,boolean isMaxPlayer){
        int max=Integer.MIN_VALUE;
        int min=Integer.MAX_VALUE;
        if(depth==0){
            return evaluateScore();
        }
        boolean[][] eval=new boolean[N][N];
        for(int i=0;i<N;i++){
            for(int j=0;j<N;j++){
                if(map[i][j]!=0){
                    int m=Math.min(i+2,N-1);
                    int m2=Math.min(j+2,N-1);
                    for(int k=Math.max(0,i-2);k<=m;k++){
                        for(int l=Math.max(0,j-2);l<=m2;l++){
                            if(map[k][l]==0&&!eval[k][l]){
                                eval[k][l]=true;
                                if(isMaxPlayer){
                                    map[k][l]=color;
                                    int num=AlphaBeta(depth-1,alpha,beta,false);
                                    if(depth==this.depth&&max<num){
                                        max=num;
                                        this.x=k;
                                        this.y=l;
                                    }
                                    max=Math.max(max,num);
                                    alpha=Math.max(max,alpha);
                                    map[k][l]=0;
                                    if(alpha>=beta){
                                        return max;
                                    }
                                }else{
                                    map[k][l]=-color;
                                    int num=AlphaBeta(depth-1,alpha,beta,true);
                                    min=Math.min(min,num);
                                    beta=Math.min(min,beta);
                                    map[k][l]=0;
                                    if(alpha>=beta){
                                        return min;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return isMaxPlayer?max:min;
    }
    private int evaluateScore() {
        return rowEval(color)+colEval(color)+leftEval(color)+rightEval(color)-rowEval(-color)-colEval(-color)-leftEval(-color)-rightEval(-color);
    }
    private int rowEval(int color) {//竖直方向
        StringBuilder sb=new StringBuilder();
        int value=0;
        for(int i=0;i<N;i++) {
            for (int j = 0; j < N; j++) {
                if (map[j][i] == color) {
                    sb.append('1');
                } else if (map[j][i] == 0) {
                    sb.append('0');
                } else {
                    sb.append('2');
                }
            }
            value += getScore(sb.toString());
            sb.setLength(0);
        }
        return value;
    }

    private int colEval(int color) {//水平方向
        StringBuilder sb=new StringBuilder();
        int value=0;
        for(int i=0;i<N;i++){
            for(int j=0;j<N;j++){
                if(map[i][j]==color){
                    sb.append('1');
                }else if(map[i][j]==0){
                    sb.append('0');
                }else{
                    sb.append('2');
                }
            }
            value+=getScore(sb.toString());
            sb.setLength(0);
        }
        return value;
    }
    private int leftEval(int color){//左斜
        StringBuilder sb=new StringBuilder();
        int value=0;
        for(int i=0;i<N;i++){
            for(int j=0;j<=i;j++){
                int x=j;
                int y=i-j;
                if(map[x][y]==color){
                    sb.append('1');
                }else if(map[x][y]==0){
                    sb.append('0');
                }else{
                    sb.append('2');
                }
            }
            value+=getScore(sb.toString());
            sb.setLength(0);
        }
        for(int i=1;i<N;i++){
            for(int j=i;j<N;j++){
                int x=j;
                int y=N-x+i-1;
                if(map[x][y]==color){
                    sb.append('1');
                }else if(map[x][y]==0){
                    sb.append('0');
                }else{
                    sb.append('2');
                }
            }
            value+=getScore(sb.toString());
            sb.setLength(0);
        }
        return value;
    }
    private int rightEval(int color){//右斜
        StringBuilder sb=new StringBuilder();
        int value=0;
        for(int i=0;i<N;i++) {
            for(int j=0;j<=i;j++){
                int x=j;
                int y=x+N-i-1;
                if (map[x][y] == color) {
                    sb.append('1');
                } else if (map[x][y] == 0) {
                    sb.append('0');
                } else {
                    sb.append('2');
                }
            }
            value+=getScore(sb.toString());
            sb.setLength(0);
        }
        for(int i=1;i<N;i++) {
            for(int j=i;j<N;j++){
                int x=j;
                int y=x-i;
                if (map[x][y] == color) {
                    sb.append('1');
                } else if (map[x][y] == 0) {
                    sb.append('0');
                } else {
                    sb.append('2');
                }
            }
            value+=getScore(sb.toString());
            sb.setLength(0);
        }
        return value;
    }
}
